from django.db import transaction
from rest_framework import serializers
from apps.goods.models import GoodsVisitCount, SPUSpecification, SPU, SKU, GoodsCategory, SpecificationOption, \
    SKUSpecification, SKUImage
from apps.users.models import User


class GoodsDaySerializer(serializers.ModelSerializer):
    category = serializers.CharField(read_only=True)

    class Meta:
        model = GoodsVisitCount
        fields = ['category', 'count']


class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'username', 'mobile', 'email')


class UserAddSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'username', 'mobile', 'email', 'password')
        # username字段增加长度限制，password字段只参与保存，不在返回给前端，增加write_only选项参数
        extra_kwargs = {
            'username': {
                'max_length': 20,
                'min_length': 5
            },
            'password': {
                'max_length': 20,
                'min_length': 8,
                'write_only': True

            },
        }

    # 重写create方法
    def create(self, validated_data):
        # 保存用户数据并对密码加密
        user = User.objects.create_user(**validated_data)
        return user


class SPUSpecSerializer(serializers.ModelSerializer):
    spu = serializers.CharField(read_only=True)
    spu_id = serializers.IntegerField()

    class Meta:
        model = SPUSpecification
        fields = '__all__'


class SPUSerializer(serializers.ModelSerializer):
    class Meta:
        model = SPU
        fields = '__all__'


class OptionRelationSerializer(serializers.ModelSerializer):
    class Meta:
        model = SpecificationOption
        fields = ('id', 'value')


class SPUSpecSerialzier(serializers.ModelSerializer):
    """
    规格序列化器
    """
    spu = serializers.StringRelatedField(read_only=True)
    spu_id = serializers.IntegerField()
    # 关联序列化返回 规格选项信息
    options = OptionRelationSerializer(read_only=True, many=True)

    class Meta:
        model = SPUSpecification
        fields = "__all__"


class SPUSpecRelationSerializer(serializers.Serializer):
    spec_id = serializers.IntegerField()
    option_id = serializers.IntegerField()

    # class Meta:
    #     model = SPUSpecification
    #     fields = ['spec_id', 'option_id']


class SKUSerializer(serializers.ModelSerializer):
    spu = serializers.CharField(read_only=True)
    spu_id = serializers.IntegerField()
    category = serializers.CharField(read_only=True)
    category_id = serializers.IntegerField()
    specs = SPUSpecRelationSerializer(many=True)

    class Meta:
        model = SKU
        fields = '__all__'

    def create(self, validated_data):
        specs = validated_data.pop('specs')
        with transaction.atomic():
            sid = transaction.savepoint()
            try:
                sku = super().create(validated_data)

                for item in specs:
                    item['sku_id'] = sku.id
                    SKUSpecification.objects.create(**item)
            except:
                transaction.savepoint_rollback(sid)
                raise serializers.ValidationError('创建sku失败')
            else:
                transaction.savepoint_commit(sid)
                return sku

    def update(self, instance, validated_data):
        specs = validated_data.pop('specs')
        with transaction.atomic():
            sid = transaction.savepoint()
            try:
                instance = super().update(instance, validated_data)
                SKUSpecification.objects.filter(sku_id=instance.id).delete()

                for item in specs:
                    item['sku_id'] = instance.id
                    SKUSpecification.objects.create(**item)
            except:
                transaction.savepoint_rollback(sid)
            else:
                transaction.savepoint_commit(sid)
                return instance


class GoodsCategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = GoodsCategory
        fields = ['id', 'name']


class ImageSerializer(serializers.ModelSerializer):
    class Meta:
        model = SKUImage
        fields = '__all__'
